// pkg/server/server.go
package tcplib

import (
	"cow_golang/shared_mod/logger"
	"cow_golang/shared_mod/tcplib/iface"
	"fmt"
	"github.com/sirupsen/logrus"
	"net"
	"sync/atomic"
)

type Server struct {
	//服务器名称
	Name string
	//服务器ip
	IP string
	//服务器端口
	Port int
	// ip version v4 v6
	IPVersion string
	//最大连接数
	MaxConn uint32
	//最大包长度
	MaxPacketSize uint32
	//服务器绑定的路由
	msgHandles iface.IMessageHandle
	// session 管理
	SessionMgr iface.ISessionManager

	// 创建hook方法
	OnCreateConn func(session iface.ISession)
	// 断开hook方法
	OnCloseConn func(session iface.ISession)
	// 当前session id 唯一id的位置
	CurrentSessionID uint32
}

// 设置连接创建回调方法
func (s *Server) SetCreateConnHook(f func(session iface.ISession)) {
	s.OnCreateConn = f
}

// 设置连接断开回调方法
func (s *Server) SetCloseConnHook(f func(session iface.ISession)) {
	s.OnCloseConn = f
}

// 连接创建回调方法实现
func (s *Server) OnCreateConnHook(session iface.ISession) {
	if s.OnCreateConn != nil {
		fmt.Println("call OnCreateConnHook")
		s.OnCreateConn(session)
	}
}

// 连接关闭回调方法实现
func (s *Server) OnCloseConnHook(session iface.ISession) {
	if s.OnCloseConn != nil {
		fmt.Println("call OnCreateConnHook")
		s.OnCloseConn(session)
	}
}

func (s *Server) Init() {

}

func (s *Server) AddHandle(msgID uint32, handle iface.IHandle) {
	s.msgHandles.AddHandle(msgID, handle)
	fmt.Println("[AddRouter] msgId:", msgID, " handle success")
}

func (s *Server) AddAllHandles(handles map[uint32]iface.IHandle) {
	s.msgHandles.AddAllHandles(handles)
	fmt.Println("[AddAllHandles] success")
}

func (s *Server) Start() {
	// 初始化日志
	logger.GetInstance().SetLevel(logrus.DebugLevel)
	logger.GetInstance().Debugf("[Start] server ip:%s, port:%d\n", s.IP, s.Port)
	//fmt.Printf("[Start] server ip:%s, port:%d\n", s.IP, s.Port)
	// 开启goroutine处理listen处理连接接入
	go func() {
		// 获取 tcp addr
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			logger.GetInstance().Error("resolve tcp addr error:", err)
			return
		}
		// 监听
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen error:", err)
			return
		}
		fmt.Println("start server", s.Name, " success")
		// 处理连接
		for {
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("Accept err", err)
				continue
			}
			// 检查是否达到最大连接数
			if s.SessionMgr.Len() >= int(s.MaxConn) {
				conn.Close()
				continue
			}
			// 创建session，并让session开始工作
			cid := atomic.AddUint32(&s.CurrentSessionID, 1)
			clientSession := NewSession(conn, cid, s.msgHandles, s)
			go clientSession.Start()
		}
	}()
}

func (s *Server) Stop() {
	fmt.Printf("[Stop] server ip:%s, port:%d\n", s.IP, s.Port)
	// 服务器停止前清理连接信息
	s.SessionMgr.Clear()
}

func (s *Server) Serve() {
	s.Start()

	// 启动后还需要其他的处理

	// 阻塞
	select {}
}

func (s *Server) GetSessionMgr() iface.ISessionManager {
	return s.SessionMgr
}

/*
创建一个服务后续要使用单例的创建
*/
func NewServer(name, ip string, port int, ipVersion string) *Server {
	s := &Server{
		Name:          name,
		IP:            ip,
		Port:          port,
		IPVersion:     ipVersion,
		MaxConn:       MaxConn,
		MaxPacketSize: MaxPacketSize,
		// 创建消息处理map
		msgHandles: NewMessageHandle(),
		// session管理
		SessionMgr: NewSessionManager(),
	}
	return s
}
